<?php
/**
 * Author: yixuan
 * Desc:
 * Time: 2016/7/18 09:14
 */

namespace app\mobile\controller;

use app\model\Pay;
use think\Controller;
use think\Db;
use app\model\Payment as PaymentModel;

class Payment extends Controller
{
    /**
     * Desc:支付通知回调
     * Author: yixuan
     * Time: 2016/8/11 13:35
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function notify()
    {
        global $_G, $_P;
        $xmlData = file_get_contents('php://input');
        $notifyData = xmlToArray($xmlData);
        yxlog(['type' => '回调接收参数', 'data' => $notifyData], '微信支付');
        //判断通知参数是否为空
        if (empty($notifyData)) {
            $return_res = [
                'return_code' => 'FAIL',
                'return_msg' => '通知数据为空'
            ];
            echo array2xml($return_res);
            exit();
        }
        //判断通知状态码、业务码是否正常
        if ($notifyData['return_code'] != 'SUCCESS' || $notifyData['result_code'] != 'SUCCESS') {
            yxlog(['type' => '回调通知异常', 'data' => $notifyData], '微信支付');
            $return_res = [
                'return_code' => 'FAIL',
                'return_msg' => empty($notifyData['return_msg']) ? $notifyData['err_code_des'] : $notifyData['return_msg']
            ];
            echo array2xml($return_res);
            exit();
        }
        //根据返回的attach 查询module_name
        $format_attach = explode('-', $notifyData['attach']);
        $module_name = $format_attach[0];
        $themeid = $format_attach[1];
        $notify_orderid = $format_attach[2];
        $payment = [];
        //通过paylog 查询相关信息
        $log = Db::table('yx_sys_paylog')->where(['uniontid' => $notifyData['out_trade_no']])->find();
        if ($log) {
            //通过查询平台的设置表
            $platform_item = Db::table('yx_sys_platform')->where(['id' => $log['mpid']])->find();
            if ($platform_item && $platform_item['mchid'] && $platform_item['apikey']) {
                $payment['mchid'] = $platform_item['mchid'];
                $payment['signkey'] = $platform_item['apikey'];
                $payment['apikey'] = $platform_item['apikey'];
                //若活动编号最后一位为1 收款则用发红包的商户号，仅限易宣公众号
                $softid = substr($log['module'], -5);
                if (DOMAIN1 != 'www.yixuan.net' && $softid % 10 == 1 && $log['mpid'] == 2) {
                    $serverconfigs = Db::name('00serverconfig')->where('id', 'neq', 0)->find();
                    $serverconfig = !empty($serverconfigs['settings']) ? xunserializer($serverconfigs['settings']) : [];
                    if (!empty($serverconfig) && $serverconfig['mchid2'] && $serverconfig['apikey2']) {
                        $payment['mchid'] = $serverconfig['mchid2'];
                        $payment['signkey'] = $serverconfig['apikey2'];
                        $payment['apikey'] = $serverconfig['apikey2'];
                    }
                }
            } else {
                $module = Db::table('yx_sys_modules')->where(['module_name' => $log['module'], 'themeid' => $themeid])->find();
                if ($module) {
                    $serverconfig = !empty($module['system']) ? json_decode($module['system'], true) : [];
                    if ($serverconfig && $serverconfig['mchid'] && $serverconfig['apikey']) {
                        $payment['mchid'] = $serverconfig['mchid'];
                        $payment['signkey'] = $serverconfig['apikey'];
                        $payment['apikey'] = $serverconfig['apikey'];
                    }
                }
            }
        }
        if (!$log) {
            //支付日志表未查询到相关记录 通过返回的attach参数去module表查询
            $module = Db::table('yx_sys_modules')->where(['module_name' => $module_name, 'themeid' => $themeid])->find();
            if ($module) {
                $serverconfig = !empty($module['system']) ? json_decode($module['system'], true) : [];
                if ($serverconfig && $serverconfig['mchid'] && $serverconfig['apikey']) {
                    $payment['mchid'] = $serverconfig['mchid'];
                    $payment['signkey'] = $serverconfig['apikey'];
                    $payment['apikey'] = $serverconfig['apikey'];
                }
            }
        }
        //支付参数异常 记录日志
        if (empty($payment)) {
            yxlog(['type' => '回调支付参数异常', 'data' => $notifyData], '微信支付');
            $return_res = [
                'return_code' => 'FAIL',
                'return_msg' => ''
            ];
            echo array2xml($return_res);
            exit();
        }
        //签名验证
        if (!$this->validateSign($notifyData, $payment['signkey'])) {
            yxlog(['type' => '回调验证签名失败', 'notifyData' => $notifyData, 'payment' => $payment], '微信支付');
            $return_res = [
                'return_code' => 'FAIL',
                'return_msg' => '签名验证失败'
            ];
            echo array2xml($return_res);
            exit();
        }
        //再次查询paylog表 商户订单号一致的记录
        $log = Db::table('yx_sys_paylog')->where(['uniontid' => $notifyData['out_trade_no']])->find();
        //验证支付状态以及金额是否一致
        if ($log && $log['status'] == '0' && (($notifyData['total_fee'] / 100) == $log['fee'])) {
            $log['tag'] = xunserializer($log['tag']);
            $log['tag']['transaction_id'] = $notifyData['transaction_id'];
            $log['uid'] = $log['tag']['uid'];
            $record = ['status' => 1, 'tag' => xserializer($log['tag'])];
            Db::table('yx_sys_paylog')->where(['id' => $log['id']])->update($record);
            $ret = [];
            $ret['mpid'] = $log['mpid'];
            $ret['result'] = 'success';
            $ret['from'] = 'notify';
            $ret['tid'] = $log['tid'];
            $ret['uniontid'] = $log['uniontid'];
            $ret['transaction_id'] = $log['transaction_id'];
            $ret['trade_type'] = $notifyData['trade_type'];
            $ret['follow'] = $notifyData['is_subscribe'] == 'Y' ? 1 : 0;
            $ret['user'] = empty($notifyData['openid']) ? $log['openid'] : $notifyData['openid'];
            $ret['fee'] = $log['fee'];
            $ret['tag'] = $log['tag'];
            $ret['card_fee'] = $log['fee'];
            if (!empty($get['time_end'])) {
                $ret['paytime'] = strtotime($notifyData['time_end']);
            }
            if ($notify_orderid) {
                $ret['orderid'] = $notify_orderid;
            }
            //通过传递相关参数调用 定义常量
            $module = Db::table('yx_sys_modules')->where(['module_name' => $log['module'], 'themeid' => $themeid])->find();
            $_G['mpid'] = $log['mpid'];
            $_G['system'] = empty($module['system']) ? array() : json_decode($module['system'], true);
            $server_confg_t = Db::name('00serverconfig')->find();
            $server_confg = empty($server_confg_t) ? array() : json_decode($server_confg_t['config'], true);
            $_G['system']['s'] = $server_confg; //临时将所有的参数$system
            yxlog(['type' => '回调通知成功', 'ret' => $ret], '微信支付');
            Pay::payResult($ret);
            //根据当前module_name 挂载全局的system
            $return_res = [
                'return_code' => 'SUCCESS',
                'return_msg' => 'OK'
            ];
            echo array2xml($return_res);
            exit();
        }
    }

    /**
     * Desc:验证签名
     * Author: yixuan
     * Time: 2016/7/18 09:18
     * @param $data //待验证的数据
     * @return bool //签名是否有效
     */
    private function validateSign($data, $signkey)
    {
        $sign = $data['sign'];
        unset($data['sign']);
        ksort($data);
        $stringToSign = urldecode(http_build_query($data)) . '&key=' . $signkey;
        $calculatedSign = strtoupper(md5($stringToSign));
        return $calculatedSign === $sign;
    }

    /**
     * Desc:微信jspai构造预支付订单信息
     * Author: yixuan
     * Time: 2016/8/11 13:35
     * @return \think\response\View
     * @throws \think\Exception
     * @throws \think\exception\PDOException
     */
    public function pay()
    {
        global $_G, $_P;
        $get_data = input();
        $done = $get_data['done'];
        $sl = $get_data['sl'];
        $params = json_decode(base64_decode($sl), true);
        $log = db_get('yx_sys_paylog', ['tid' => $params['tid']]);
        $module = Db::table('yx_sys_modules')->where(['module_name' => $log['module'], 'themeid' => $params['themeid']])->find();
        if ($module) {
            !defined('MODULE_NAME') && define('MODULE_NAME', $log['module']);
            $_P['themeid'] = $params['themeid'];
            $_G['mpid'] = $log['mpid'];
            $_G['system'] = $module['system'] = empty($module['system']) ? array() : json_decode($module['system'], true);
            $_G['theme'] = $module['theme'] = empty($module['theme']) ? array() : json_decode($module['theme'], true);
        }
        if ($done == '1') {
            //paylog记录存在 微信支付通知成功
            if (!empty($log) && !empty($log['status'])) {
                $ret = [
                    'mpid' => $log['mpid'],
                    'result' => 'success',
                    'from' => 'return',
                    'tid' => $log['tid'],
                    'uniontid' => $log['uniontid'],
                    'user' => $log['openid'],
                    'fee' => $log['fee'],
                    'tag' => $log['tag'],
                    'card_fee' => $log['fee']
                ];
                exit(Pay::payResult($ret));
            }
            //支付异常 返回活动首页
            $url = $_G['siteroot'] . createMobileUrl('index', array('fopenid' => $params['openid'], 'fromuid' => $params['uid'], 'themeid' => $params['themeid']));
            echo "<script language='javascript' type='text/javascript'>";
            echo "window.location.href='$url';";
            echo "</script>";
            exit;
        }
        if ($params && $params['title']) {
            $params['title'] = urldecode($params['title']);
        }
        if (!empty($log) && $log['status'] != '0') {
            return_msg('这个订单已经支付成功, 不需要重复支付.');
        }
        $auth = sha1($sl . $log['mpid'] . MODULE_NAME);
        if ($auth != $get_data['auth']) {
            return_msg('参数传输错误.');
        }
        $platform_item = db_get('yx_sys_platform', ['id' => $log['mpid']]);

        if ($platform_item && $platform_item['mchid'] && $platform_item['apikey']) {
            $wechat['appid'] = $platform_item['appid'];
            $wechat['mchid'] = $platform_item['mchid'];
            $wechat['apikey'] = $wechat['signkey'] = $platform_item['apikey'];

            $softid = substr($log['module'], -5);
            $serverconfigs = Db::name('00serverconfig')->where('id', 'neq', 0)->find();
            $serverconfig = !empty($serverconfigs['settings']) ? xunserializer($serverconfigs['settings']) : [];
            if (DOMAIN1 != 'www.yixuan.net' && $softid % 10 == 1 && !empty($serverconfig['mchid2'])) {
                //判断易宣放行
            } else {
                //判断与system不一致拦截
                if ($wechat['mchid'] != $_G['system']['mchid']) {
                    return return_msg('-2参数设置商户信息与平台设置信息不一致');
                }
            }
            //易宣修改：若软件编号最后一位,收款则用发红包的商户号,仅限易宣公众号
            $softid = substr($log['module'], -5);
            if (DOMAIN1 != 'www.yixuan.net' && $softid % 10 == 1 && $log['mpid'] == 2) {
                $serverconfigs = Db::name('00serverconfig')->where('id', 'neq', 0)->find();
                $serverconfig = !empty($serverconfigs['settings']) ? xunserializer($serverconfigs['settings']) : [];
                if (!empty($serverconfig) && $serverconfig['mchid2'] && $serverconfig['apikey2']) {
                    $wechat['mchid'] = $serverconfig['mchid2'];
                    $wechat['signkey'] = $serverconfig['apikey2'];
                    $wechat['apikey'] = $serverconfig['apikey2'];
                }
            }
        } else {
            if (!$module) {
                return return_msg('-3参数设置商户信息与平台设置信息不一致');
            }
            $wechat['appid'] = $module['system']['appid'];
            $wechat['mchid'] = $module['system']['mchid'];
            $wechat['apikey'] = $wechat['signkey'] = $module['system']['apikey'];
        }

        $pre_pay_res = PaymentModel::unifiedorder($params, $wechat);
        if ($pre_pay_res['errcode'] == 1) {
            if ($pre_pay_res['msg'] == 'invalid out_trade_no' || $pre_pay_res['msg'] == 'OUT_TRADE_NO_USED') {
                $tmp_id = date('YmdH');
                Db::table('yx_sys_paylog')->where(['id' => $log['id']])->update(['id' => $tmp_id]);
                Db::query("ALTER TABLE `yx_sys_paylog` auto_increment = " . ($tmp_id + 1) . ";");
                return_msg("抱歉，发起支付失败，具体原因为：“{$pre_pay_res['errcode']}:{$pre_pay_res['msg']}”。请及时联系站点管理员。");
            } else {
                return_msg($pre_pay_res['msg'], '', 'info');
            }
        }
        $pre_params = $pre_pay_res['data'];
        $return_clicent = get_defined_vars();
        return view('base/paycenter', $return_clicent);
    }

    public function refund()
    {
        yxlog('微信退款通知');
        $xmlData = file_get_contents('php://input');
        if (empty($xmlData)) {
            $return_res = [
                'return_code' => 'FAIL',
                'return_msg' => '通知数据为空'
            ];
            echo array2xml($return_res);
            exit();
        }
        $notifyData = xmlToArray($xmlData);
        if (empty($notifyData)) {
            $return_res = [
                'return_code' => 'FAIL',
                'return_msg' => '通知数据为空'
            ];
            echo array2xml($return_res);
            exit();
        }
        if ($notifyData['return_code'] != 'SUCCESS') {
            $return_res = [
                'return_code' => 'FAIL',
                'return_msg' => $notifyData['return_msg']
            ];
            echo array2xml($return_res);
            exit();
        }
    }
}